package com.pitop.base.interceptor;

import com.opensso.sdk.client.SSOClient;
import com.opensso.sdk.client.SessionEnum;
import com.opensso.sdk.security.JwtToken;
import com.opensso.sdk.tools.SessionTools;
import com.pitop.account.entity.Account;
import com.pitop.account.service.AccountSVImpl;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.tools.CookieTools;
import com.pitop.core.tools.redis.RedisUtils;
import com.pitop.setting.entity.Setting;
import com.pitop.setting.service.SettingSVImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * LoginInterceptor
 */
@Component
@Slf4j
public class LoginInterceptor_bak implements HandlerInterceptor {

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private SettingSVImpl settingSVImpl;//设置
    @Resource
    private AccountSVImpl accountSVImpl;//账户

    /**
     * 登录拦截器，拦截token的合法性
     * 1.获取token
     * 2.验证局部会话是否存在,存在则刷新过期时间
     * 3.通过ssoclient验证
     * 4.验证通过建立局部会话
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取token
        String token = request.getHeader(SessionEnum.Authorization.name());

        if (StringUtils.isBlank(token)) {
            throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
        }

        log.debug("token::: " + token);
        String sso_apikey = settingSVImpl.loadByK(Setting.Key.SSO_ApiKey.name()).getV();
        String sso_host = settingSVImpl.loadByK(Setting.Key.SSO_HOST.name()).getV();

        if (StringUtils.isNotBlank(token)) {
            String sso_apisecret = settingSVImpl.loadByK(Setting.Key.SSO_ApiSecret.name()).getV();
            String accountStr = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Account.name());
            String sessionKey = SessionTools.Instance.genSessionKey(accountStr);
            String session_expire_timeStr = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Session_Expire_Time.name());
            if (session_expire_timeStr == null) {
                log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
                throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
            }
            int session_expire_time = Integer.parseInt(session_expire_timeStr);
            String accountCode = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Code.name());
            Account accountLoad = accountSVImpl.loadByCode(accountCode);
            if (accountLoad == null) {
                log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
                throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
            }
            //2.验证局部会话是否存在,存在则刷新过期时间
            //刷新过期时间
            String refreshTokenTimeout = SSOClient.Instance
                    .host(sso_host)
                    .apikey(sso_apikey)
                    .token(token)
                    .refreshTokenTimeout();

            if (refreshTokenTimeout == null) {
                log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
                throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
            }

            if (redisUtils.hasKey(sessionKey)) {
                redisUtils.expire(sessionKey, session_expire_time);//刷新局部会话过期时间
                CookieTools.Instance.addCookie(SessionEnum.Token.name(), refreshTokenTimeout, this.domain(request), response);//重新设置cookie
                return true;
            }
            token = refreshTokenTimeout;
        }

        //3.通过ssoclient验证
        boolean isVerify = SSOClient.Instance
                .host(sso_host)
                .apikey(sso_apikey)
                .token(token)
                .verifyToken();

        if (!isVerify) {
            log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
            throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
        }

        String sso_apisecret = settingSVImpl.loadByK(Setting.Key.SSO_ApiSecret.name()).getV();
        String accountStr = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Account.name());
        String sessionKey = SessionTools.Instance.genSessionKey(accountStr);
        String session_expire_timeStr = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Session_Expire_Time.name());
        if (session_expire_timeStr == null) {
            log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
            throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
        }
        int session_expire_time = Integer.parseInt(session_expire_timeStr);
        String accountCode = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Code.name());
        Account accountLoad = accountSVImpl.loadByCode(accountCode);
        if (accountLoad == null) {
            log.error(BaseException.BaseExceptionEnum.Session_Error.toString());
            throw new BaseException(BaseException.BaseExceptionEnum.Session_Error);
        }
        //4.验证通过建立局部会话
        //缓存对象作为会话内容
        redisUtils.set(sessionKey, accountLoad, session_expire_time);
        response.addHeader(SessionEnum.Token.name(), token);
        CookieTools.Instance.addCookie(SessionEnum.Token.name(), token, this.domain(request), response);//重新设置cookie
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    //获得域名
    private String domain(HttpServletRequest request) {
        StringBuffer url = request.getRequestURL();
        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
        tempContextUrl = tempContextUrl.replace("http://", "").replace("https://", "");
        return tempContextUrl;
    }

}